(defun* first (c) (car c))
(defun* second (c) (car (cdr c)))
(defun* third (c) (car (cdr (cdr c))))

(defmacro* defun (name args &rest body)
  `(defun* ,name ,args
     (block ,name
	,@body)))

(defmacro* dotimes (spec &rest body)
  (let ((var (first spec))
	(max (second spec)))
    `(block a
	    (let ((,var 0) (max* ,max))
	      (while*
	       (if (not (< ,var max*))
		   (return-from a t))
	       ,@body
	       (setq ,var (+ 1 ,var)))))))

(defmacro* dolist (spec &rest body)
  (let ((var (first spec))
	(lst (second spec)))
    `(let ((l ,lst))
       (block a
	      (while*
	       (if (not l) (return-from a t))
	       (let ((,var (car l)))
		 ,@body)
	       (setq l (cdr l)))))))
		

(setq newline (elt "
" 0))

(defun* write-line (str &optional (s nil))
  (dotimes (i (length str))
    (if s (write-char (elt str i) s)
      (write-char (elt str i))))
  (if s (write-char newline s)
    (write-char newline))
  t)

(defmacro* with-open-file (spec &rest body)
  `(let ((,(car spec) (open* ,(second spec))))
     ,@body
     (close* ,(car spec))))

(defmacro* == (&rest args)
  `(eq ,@args))

(defun = (&rest rest)
  (apply #'eq rest))

(defun fibeq (n)
  (if (eq n 0) 0
    (if (eq n 1) 1
      (+ (fibeq (- n 1)) (fibeq (- n 2))))))

(defun fibapply (n)
  (if (= n 0) 0
    (if (= n 1) 1
      (+ (fibapply (- n 1)) (fibapply (- n 2))))))

(defun fibmacro (n)
  (if (== n 0) 0
    (if (== n 1) 1
      (+ (fibmacro (- n 1)) (fibmacro (- n 2))))))
